import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { environment } from '../../../environments/environment';
import { 
  Breakpoint, 
  DebugSession, 
  DebugEvent, 
  DebugRequest, 
  DebugResponse, 
  DebugVariable,
  StackFrame,
  WatchExpression 
} from './debug.interface';

@Injectable({
  providedIn: 'root'
})
export class DebuggerService {
  private ws: WebSocket | null = null;
  private sessionSubject = new BehaviorSubject<DebugSession | null>(null);
  private eventSubject = new Subject<DebugEvent>();
  private outputSubject = new Subject<string>();
  
  public session$ = this.sessionSubject.asObservable();
  public events$ = this.eventSubject.asObservable();
  public output$ = this.outputSubject.asObservable();

  private currentSession: DebugSession | null = null;
  private sessionId: string = '';

  constructor() {
    this.sessionId = this.generateSessionId();
  }

  private generateSessionId(): string {
    return 'debug-session-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
  }

  // 启动调试会话
  async startDebugSession(code: string, language: string, input?: string): Promise<boolean> {
    try {
      // 建立WebSocket连接
      await this.connectToDebugServer();
      
      const session: DebugSession = {
        id: this.sessionId,
        state: 'stopped',
        threads: [{ id: 1, name: 'Main Thread' }],
        stackFrames: [],
        variables: [],
        breakpoints: []
      };

      // 发送启动请求
      const request: DebugRequest = {
        type: 'launch',
        sessionId: this.sessionId,
        data: {
          code: code,
          language: language,
          input: input,
          breakpoints: session.breakpoints
        }
      };

      this.sendRequest(request);
      this.currentSession = session;
      this.sessionSubject.next(session);
      
      return true;
    } catch (error) {
      console.error('Failed to start debug session:', error);
      return false;
    }
  }

  // 连接到调试服务器
  private connectToDebugServer(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        resolve();
        return;
      }

      const wsUrl = environment.apiUrl.replace(/^http/, 'ws') + '/debug';
      this.ws = new WebSocket(wsUrl);

      this.ws.onopen = () => {
        console.log('Debug WebSocket connected');
        resolve();
      };

      this.ws.onmessage = (event) => {
        this.handleServerMessage(JSON.parse(event.data));
      };

      this.ws.onerror = (error) => {
        console.error('Debug WebSocket error:', error);
        reject(error);
      };

      this.ws.onclose = () => {
        console.log('Debug WebSocket disconnected');
        this.handleSessionTerminated();
      };
    });
  }

  // 处理服务器消息
  private handleServerMessage(message: any) {
    switch (message.type) {
      case 'event':
        this.handleDebugEvent(message.data);
        break;
      case 'response':
        this.handleDebugResponse(message.data);
        break;
      case 'output':
        this.outputSubject.next(message.data.text);
        break;
    }
  }

  // 处理调试事件
  private handleDebugEvent(event: DebugEvent) {
    if (!this.currentSession) return;

    switch (event.type) {
      case 'stopped':
        this.currentSession.state = 'stopped';
        this.currentSession.currentLine = event.line;
        this.requestStackTrace();
        this.requestVariables();
        break;
      case 'continued':
        this.currentSession.state = 'running';
        this.currentSession.currentLine = undefined;
        break;
      case 'terminated':
        this.handleSessionTerminated();
        break;
      case 'output':
        this.outputSubject.next(event.text || '');
        break;
    }

    this.sessionSubject.next(this.currentSession);
    this.eventSubject.next(event);
  }

  // 请求调用栈
  private requestStackTrace() {
    if (!this.currentSession) return;
    
    const request: DebugRequest = {
      type: 'evaluate',
      sessionId: this.sessionId,
      data: { command: 'stackTrace' }
    };
    this.sendRequest(request);
  }

  // 请求变量信息
  private requestVariables() {
    if (!this.currentSession) return;
    
    const request: DebugRequest = {
      type: 'evaluate',
      sessionId: this.sessionId,
      data: { command: 'variables' }
    };
    this.sendRequest(request);
  }

  // 处理调试响应
  private handleDebugResponse(response: DebugResponse) {
    if (!this.currentSession) return;

    if (response.data) {
      if (response.data.stackFrames) {
        this.currentSession.stackFrames = response.data.stackFrames;
      }
      if (response.data.variables) {
        this.currentSession.variables = response.data.variables;
      }
      this.sessionSubject.next(this.currentSession);
    }
  }

  // 断点管理
  setBreakpoint(line: number, condition?: string, logMessage?: string): Breakpoint {
    if (!this.currentSession) {
      throw new Error('No active debug session');
    }

    const breakpoint: Breakpoint = {
      id: `bp-${line}-${Date.now()}`,
      line: line,
      condition: condition,
      enabled: true,
      verified: false,
      type: logMessage ? 'logpoint' : (condition ? 'conditional' : 'line'),
      logMessage: logMessage
    };

    this.currentSession.breakpoints.push(breakpoint);
    this.syncBreakpoints();
    
    return breakpoint;
  }

  removeBreakpoint(breakpointId: string) {
    if (!this.currentSession) return;

    this.currentSession.breakpoints = this.currentSession.breakpoints.filter(
      bp => bp.id !== breakpointId
    );
    this.syncBreakpoints();
  }

  toggleBreakpoint(breakpointId: string) {
    if (!this.currentSession) return;

    const breakpoint = this.currentSession.breakpoints.find(bp => bp.id === breakpointId);
    if (breakpoint) {
      breakpoint.enabled = !breakpoint.enabled;
      this.syncBreakpoints();
    }
  }

  // 同步断点到服务器
  private syncBreakpoints() {
    if (!this.currentSession) return;

    const request: DebugRequest = {
      type: 'setBreakpoints',
      sessionId: this.sessionId,
      data: {
        breakpoints: this.currentSession.breakpoints.filter(bp => bp.enabled)
      }
    };
    this.sendRequest(request);
  }

  // 调试控制
  continue() {
    this.sendControlCommand('continue');
  }

  stepOver() {
    this.sendControlCommand('next');
  }

  stepInto() {
    this.sendControlCommand('stepIn');
  }

  stepOut() {
    this.sendControlCommand('stepOut');
  }

  pause() {
    this.sendControlCommand('pause');
  }

  terminate() {
    this.sendControlCommand('terminate');
  }

  private sendControlCommand(command: string) {
    if (!this.currentSession) return;

    const request: DebugRequest = {
      type: command as any,
      sessionId: this.sessionId
    };
    this.sendRequest(request);
  }

  // 表达式求值
  evaluateExpression(expression: string): Promise<string> {
    return new Promise((resolve, reject) => {
      if (!this.currentSession) {
        reject('No active debug session');
        return;
      }

      const request: DebugRequest = {
        type: 'evaluate',
        sessionId: this.sessionId,
        data: {
          expression: expression,
          context: 'repl'
        }
      };

      // 这里需要实现一个请求-响应机制
      // 简化版本直接返回
      this.sendRequest(request);
      
      // 监听响应（实际应该有更完善的请求-响应匹配机制）
      const subscription = this.events$.subscribe(event => {
        if (event.type === 'output') {
          resolve(event.text || '');
          subscription.unsubscribe();
        }
      });
    });
  }

  // 发送请求到服务器
  private sendRequest(request: DebugRequest) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        type: 'request',
        data: request
      }));
    }
  }

  // 处理会话终止
  private handleSessionTerminated() {
    if (this.currentSession) {
      this.currentSession.state = 'terminated';
      this.sessionSubject.next(this.currentSession);
    }
    
    this.currentSession = null;
    
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  // 获取当前会话
  getCurrentSession(): DebugSession | null {
    return this.currentSession;
  }

  // 清理资源
  dispose() {
    this.handleSessionTerminated();
  }
} 